﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using OpenPhotoAlbum.DbAccess;
using OpenPhotoAlbum.BusinessLogics;
using System.IO;
using OpenPhotoAlbum.Controls;
using System.Drawing.Imaging;
using System.Drawing;

namespace OpenPhotoAlbum
{
    /// <summary>
    /// Summary description for $codebehindclassname$
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class PhotoPipe : IHttpHandler
    {
		public static byte[] postPadCanvasCache = null;
		public static object postPadCanvasCache_LockSignal = new object();

		private const string BANNED = "~/App_Themes/Classic/Images/b.jpg";
		private const string BANNED_LARGE = "~/App_Themes/Classic/Images/b_l.jpg";
		private const string BANNED_AC = "~/App_Themes/Classic/Images/b_ac.jpg";
		private const string NOT_FOUND = "~/App_Themes/Classic/Images/n.jpg";
		private const string NOT_FOUND_LARGE = "~/App_Themes/Classic/Images/n_l.jpg";
		private const string NOT_FOUND_AC = "~/App_Themes/Classic/Images/n_ac.jpg";

		private bool IsAdministrator
		{
			get
			{
				return UserManager.Instance.IsAdministrator(HttpContext.Current.User.Identity.Name);
			}
		}

        public void ProcessRequest(HttpContext context)
        {
			string type = context.Request.QueryString[UrlFormats.PARAMETER_NAME_PHOTO_TYPE];

			if (type == PhotoTypes.Captcha)
			{
				ReadCaptcha(context, UrlContext.Data);
				return;
			}

			if (type == PhotoTypes.UserIcon)
			{
				if (UrlContext.UserId.Equals(Guid.Empty)) { ProcessEmptyIcon(context); }
				else { ReadIcon(context, UrlContext.UserId); }
				return;
			}

            string id = context.Request.QueryString[UrlFormats.PARAMETER_NAME_PHOTO_ID];
            if (string.IsNullOrEmpty(id)){ ProcessEmptyPhoto(context); return; }

            Guid photoId = Guid.Empty;
            try { photoId = new Guid(id); }
            catch (Exception) { ProcessEmptyPhoto(context); return; }

            context.Response.Clear();
			switch (type)
			{
				case PhotoTypes.Thumbnail: ReadThumbnail(context, photoId); break;
				case PhotoTypes.SmallThumbnail: ReadSmallThumbnail(context, photoId); break;
				case PhotoTypes.FullSize: ReadFullSize(context, photoId); break;
				case PhotoTypes.AlbumCover: ReadAlbumCover(context, photoId); break;
				case PhotoTypes.PostPadCanvas: ReadPostPadCanvas(context); break;
				default: ProcessEmptyPhoto(context); break;
			}
            context.Response.End();
        }

        private void ProcessEmptyPhoto(HttpContext context)
        {
			if (UrlContext.PhotoType == PhotoTypes.FullSize) { context.Response.Redirect(NOT_FOUND_LARGE); }
			else if (UrlContext.PhotoType == PhotoTypes.Thumbnail) { context.Response.Redirect(NOT_FOUND); }
			else if (UrlContext.PhotoType == PhotoTypes.SmallThumbnail) { context.Response.Redirect(NOT_FOUND); }
			else if (UrlContext.PhotoType == PhotoTypes.AlbumCover) { context.Response.Redirect(NOT_FOUND_AC); }
        }

		private void ProcessBannedPhoto(HttpContext context)
		{
			if (UrlContext.PhotoType == PhotoTypes.FullSize) { context.Response.Redirect(BANNED_LARGE); }
			else if (UrlContext.PhotoType == PhotoTypes.Thumbnail) { context.Response.Redirect(BANNED); }
			else if (UrlContext.PhotoType == PhotoTypes.SmallThumbnail) { context.Response.Redirect(BANNED); }
			else if (UrlContext.PhotoType == PhotoTypes.AlbumCover) { context.Response.Redirect(BANNED_AC); }
		}

		private void ProcessEmptyIcon(HttpContext context)
		{
			context.Response.Redirect(Links.DefaultUserIcon);
		}

		private void ReadThumbnail(HttpContext context, Guid photoId)
		{
			Photo photo = PhotoManager.Instance.GetPhoto(photoId);
			if (photo == null) { ProcessEmptyPhoto(context); return; }
			if (photo.IsBanned && !this.IsAdministrator) { ProcessBannedPhoto(context); return; }

			context.Response.ContentType = photo.PhotoThumbnailContentType;
			context.Response.BinaryWrite(photo.PhotoThumbnailData.ToArray());
		}

		private void ReadSmallThumbnail(HttpContext context, Guid photoId)
		{
			Photo photo = PhotoManager.Instance.GetPhoto(photoId);
			if (photo == null) { ProcessEmptyPhoto(context); return; }
			if (photo.IsBanned && !this.IsAdministrator) { ProcessBannedPhoto(context); return; }

			byte[] data = BusinessLogics.PhotoManager.Instance.ResizePhotoToByteArray(
				photo.PhotoThumbnailData.ToArray(),
				BusinessLogics.PhotoManager.SMALL_TH_MAX_WIDTH,
				BusinessLogics.PhotoManager.SMALL_TH_MAX_HEIGHT);

			context.Response.ContentType = photo.PhotoThumbnailContentType;
			context.Response.BinaryWrite(data);
		}

		private void ReadFullSize(HttpContext context, Guid photoId)
		{
			Photo photo = PhotoManager.Instance.GetPhoto(photoId);
			if (photo == null) { ProcessEmptyPhoto(context); return; }
			if (photo.IsBanned && !this.IsAdministrator) { ProcessBannedPhoto(context); return; }

			byte[] data = photo.PhotoData.ToArray();

			Controls.PhotoProcessors.IPhotoProcessor processor = null;

			if (!string.IsNullOrEmpty(UrlContext.VisualEffect))
			{
				processor = Controls.PhotoProcessors.ProcessorFactory.CreateProcessor(UrlContext.VisualEffect);
				data = processor.Process(photo.PhotoData.ToArray());
			}
			context.Response.ContentType = photo.PhotoContentType;
			context.Response.BinaryWrite(data);
		}

		private void ReadAlbumCover(HttpContext context, Guid photoId)
		{
			Photo photo = PhotoManager.Instance.GetPhoto(photoId);
			if (photo == null) { ProcessEmptyPhoto(context); return; }
			if (photo.IsBanned && !this.IsAdministrator) { ProcessBannedPhoto(context); return; }

			byte[] data = BusinessLogics.PhotoManager.Instance.PaintAlbumCover(photo.PhotoThumbnailData.ToArray());

			context.Response.ContentType = photo.PhotoThumbnailContentType;
			context.Response.BinaryWrite(data);
		}

		private void ReadPostPadCanvas(HttpContext context)
		{
			lock (postPadCanvasCache_LockSignal)
			{
				if (postPadCanvasCache == null)
				{
					FileStream fs = new FileStream(context.Server.MapPath(Links.PostPadCanvas), FileMode.Open, FileAccess.Read);
					postPadCanvasCache = new byte[fs.Length];
					fs.Read(postPadCanvasCache, 0, postPadCanvasCache.Length);
					fs.Close();
				}
				context.Response.ContentType = BusinessLogics.PhotoManager.CONTENT_TYPE_JPEG;
				context.Response.BinaryWrite(postPadCanvasCache);
			}
		}

		private void ReadCaptcha(HttpContext context, string data)
		{
			int number = CaptchaDataServices.Instance.Decrypt(data);
			byte[] imageData = CaptchaPainter.Instance.Paint(number, ImageFormat.Png);

			context.Response.ContentType = BusinessLogics.PhotoManager.CONTENT_TYPE_PNG;
			context.Response.BinaryWrite(imageData);
		}

		private void ReadIcon(HttpContext context, Guid userId)
		{
			User user = BusinessLogics.UserManager.Instance.GetUser(userId);
			if (user == null || user.UserIcon == null) { ProcessEmptyIcon(context); return; }

			context.Response.ContentType = BusinessLogics.PhotoManager.CONTENT_TYPE_JPEG;
			context.Response.BinaryWrite(user.UserIcon.ToArray());
		}

        public bool IsReusable
        {
            get { return false; }
        }
    }
}
